#pragma once

#include "mockif.hpp"
#include "params.hpp"
#include "tick.h"
#include "tjm_action.hpp"
#include "trigger.hpp"
#include "types.h"
#include <cstddef>
#include <cstdint>

namespace Trade {

enum DEBUG_LEVEL
{
  DEBUG_LEVEL_NONE,
  DEBUG_STEP_BY_STEP,
  DEBUG_SHOW_DATA,
};

struct Strategy;
struct Strategy00;

struct MoneyTree
{
  MoneyTree() noexcept;
  ~MoneyTree() noexcept;

  int make_deal(const int64_t start_idx) noexcept;

#if (ONLINE_DATA_COMM)
  int make_deal_online(const int64_t start_idx) noexcept;
#endif

  void set_debug(const char* debug) noexcept;
  void set_strategy(const int strategy_id) noexcept;
  void bind_call_back_functions();

private:
  int64_t idx = 0;
  time_t t_now = 0;
  price_t hp_now = 0;
  event_t mt_event = 0;
  TICK_DATA td;
  size_t td_size = 0;
  Params* vo = nullptr;
  Strategy* strategy = nullptr;
  reached_t rchd_blines = 0;

  dir_t d_tm_near = 0;
  dir_t d_tm_far = 0;
  dir_t d_guess = 0;
  dir_t d_far = 0;
  dir_t d_near = 0;

  price_t reverse_space = 0;

  Timer tm_old_near = 0;
  Timer tm_old_far = 0;
  Timer tm_near;
  Timer tm_far;

  Lines better_lines;


  TriggerManager triggers;

  TJM tjm;
  ParamsMem vom;

  friend struct Strategy;
  friend struct Strategy00;

public:
  void set_data(const TICK_DATA td,
                const size_t td_size,
                const Params* vo,
                const size_t vo_size) noexcept;

private:
  void mock_trade() noexcept;
  int step_by_step() noexcept;
  void show_something() const noexcept;


private:
  int mt_money_tree() noexcept;
  // event_t mt_rush_hour_dir() noexcept;
  event_t mt_tjm_reached() noexcept;
  int debug_show() noexcept;
  dir_t guess_dir() noexcept;

  int on_open(const OrderPtr& o, const DealPtr& deal) noexcept;
  int on_close(const OrderPtr& o, const DealPtr& deal) noexcept;

  // int force_against_(const dir_t d) const noexcept;
  // reached_t bettler_lines_reached_() noexcept;
  // bool add_down_line_() noexcept;
  // bool add_up_line_() noexcept;
  // bool renew_better_lines_(const dir_t old_d, const dir_t new_d) noexcept;
  // int additional_line_reached_() noexcept;
  // int additional_line_reached__(const price_t hpx) noexcept;

  // bool blines_reached_line2(const dir_t d) const noexcept;
  // void update_better_lines() noexcept;

  // BigO* find_previous_bigo(const dir_t d) const noexcept;
  // BigO* find_previous_oppo_bigo(const dir_t d) const noexcept;
  // BigO* find_previous_same_bigo(const dir_t d) const noexcept;
  // int add_new_bigo(const dir_t od, const percent_t op) noexcept;
  // int calculate_reverse_force(price_t& delta) noexcept;
};

extern void
send_action(const int64_t idx,
            const time_t tm,
            const int who,
            const int action,
            const dir_t d,
            const price_t p,
            const volume_t v) noexcept;

extern void
send_reverse_space(const time_t tm,
                   const int ret,
                   const price_t delta) noexcept;

} // namespace Trade
